<?php

class RocCS {

    private $address = '127.0.0.1';
    private $port = 8051;
    private $timeout = 3;
    private $connCS = false;

    /**
     * CLASS INIT : RETRIEVE IP AND PORT
     * 
     * @param array $params array of parameters to initialize the class
     */
    function __construct($params = array()) {
        if (isset($params['ip'])) {
            $this->ip = $params['ip'];
        }
        if (isset($params['port'])) {
            $this->port = $params['port'];
        }
        if (isset($params['timeout'])) {
            $this->port = $params['timeout'];
        }

        $this->openSocket();
    }

    /**
     * SEND SWITCH COMMAND
     * 
     * @param string $switchID ID of the switch to command
     * @param string $cmd Command to send
     */
    function sendSwitchCommand($switchID, $cmd) {
        $msg = '<sw id="' . $switchID . '" cmd="' . $cmd . '"/>';
        $this->send('sw', $msg);
    }

    /*
     * GET SWITCHES PARAMETERS
     * 
     * @param array $params List of parameters to retrieve for each switch
     * 
     * @return array $switches List of requested switches
     */

    public function getSwitches($params = array('type', 'state')) {

        // Get switch list from Rocrail
        $msg = '<model cmd="swlist" />';
        $swlist = $this->get('model', $msg, 'swlist');

        // Retrieve requested switches
        if(!$swlist){
             $switches = false;
        }
        else{
            $swlistXml = new SimpleXMLElement($swlist);

            $switches = array();
            foreach ($swlistXml as $sw) {
                $switchID = (string) $sw['id'];

                foreach ($params as $param) {
                    $switches[$switchID][$param] = (string) $sw[$param];
                }
            }
        }
        return $switches;
        
    }

    /**
     * OPEN A CONNECTION WITH ROCRAIL
     */
    private function openSocket() {
        $this->connCS = @fsockopen($this->address, $this->port, $errno, $errstr, $this->timeout);

        /*
          $socket = fsockopen($this->address, $this->port, $errno, $errstr, $this->timeout);

          if (!$socket) {
          echo 'Fail to connect to Rocrail : '.$errstr.' ('.$errno.')';
          die();
          }
          else {
          $this->connCS = $socket;
          }
         */
    }

    /**
     * CREATE XML MESSAGE TO SEND TO ROCRAIL
     *
     * @param string $xmlType Node of the client service to work with
     * @param string $xmlMsg XML message to send
     * 
     * @return string $msg Formatted message with header
     */
    private function createMsg($xmlType, $xmlMsg) {
        $msg = sprintf('<xmlh><xml size="%d" name="%s"/></xmlh>%s', strlen($xmlMsg), $xmlType, $xmlMsg);
        return $msg;
    }

    /**
     * SEND MESSAGE TO ROCRAIL
     *
     * @param string $type Node of the client service to work with
     * @param string $msg XML message to send
     * 
     * @return bool Command correctly executed     
     */
    private function send($type, $msg) {

        if ($this->connCS) {
            //echo $msg."\n";
            $msg = $this->createMsg($type, $msg);

            //echo $msg."\n";

            $return = fwrite($this->connCS, $msg);

            //echo $return.'/'.strlen($msg);
            // Return ok if all characters are sent
            return ($return == strlen($msg));
        } else {
            return false;
        }
    }

    /**
     * GET MESSAGE FROM ROCRAIL
     *
     * @param string $type Node of the client service to work with
     * @param string $msg XML message to send
     * @param string $returnTag Node returned if different from $type to detect start and end of response
     * 
     * @return string $response Response from Rocrail server
     */
    private function get($type, $msg, $returnTag = '') {

        // Prepare return tag
        if ($returnTag == '') {
            $returnTag = $type;
        }
        $startTag = '<' . $returnTag . '>';
        $endTag = '</' . $returnTag . '>';


        if ($this->send($type, $msg)) {

            // Start getting response
            $return = fgets($this->connCS, 128);

            // Read resonse until end tag is detected
            while (strpos($return, $endTag) === false) {
                $return .= fgets($this->connCS, 128);
            }

            // Remove response header
            $xmlStart = strpos($return, $startTag);
            $return = substr($return, $xmlStart);

            return $return;
        }

        // Failed to send request
        else {
            return false;
        }
    }

}
